﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.Threading;

namespace Send2SMTP
{
    public class MailThread
    {
        MailThreadData m_messageData;
        public void ThreadEntryPoint(object _param)
        {
            try
            {
                Macro macroSupport = new Macro();

                m_messageData = (MailThreadData)_param;
                SmtpClient smtpClient = new SmtpClient(m_messageData.host, m_messageData.port);
                smtpClient.UseDefaultCredentials = m_messageData.useDefaultCreds;
                smtpClient.EnableSsl = m_messageData.useSSL;
                if (!m_messageData.useDefaultCreds)
                {
                    smtpClient.Credentials = new NetworkCredential(m_messageData.userName, m_messageData.password, m_messageData.domain);
                }

                //
                // Start generating messages
                while (true)
                {
                    if (m_messageData.delay > 0)
                    {
                        Thread.Sleep(m_messageData.delay);
                    }
                    Random rand;
                    //
                    // Get next unique message number
                    lock (Send2SMTP.Program.lockCount)
                    {
                        m_messageData.messageNo = Send2SMTP.Program.m_sentCount;
                        Send2SMTP.Program.m_sentCount++;
                        if (Send2SMTP.Program.m_sentCount > m_messageData.copies)
                        {
                            break;
                        }

                        //
                        // If seed<0 we want a 'purely' random number otherwise we want to associate the random
                        // sequence with the current message number.
                        if (Send2SMTP.Program.m_randomSeed < 0)
                        {
                            rand = new Random((int)DateTime.Now.Ticks);
                        }
                        else
                        {
                            rand = new Random(Send2SMTP.Program.m_randomSeed + m_messageData.messageNo);
                        }

                    }

                    using (MailMessage message = new MailMessage())
                    {
                        //
                        // From field....
                        message.From = m_messageData.from;

                        //
                        // To field...
                        if (m_messageData.toList.Count > 0)
                        {
                            foreach (MailAddress to in m_messageData.toList)
                            {
                                message.To.Add(to);
                            }
                        }

                        //
                        // CC field
                        if (m_messageData.ccList.Count > 0)
                        {
                            foreach (MailAddress cc in m_messageData.ccList)
                            {
                                message.CC.Add(cc);
                            }
                        }

                        //
                        // BCC Field
                        if (m_messageData.bccList.Count > 0)
                        {
                            foreach (MailAddress bcc in m_messageData.bccList)
                            {
                                message.Bcc.Add(bcc);
                            }
                        }

                        //
                        // Subject...
                        message.Subject = macroSupport.ParseSubjectText(m_messageData, rand, m_messageData.subject);

                        //
                        // Attachments...
                        if (m_messageData.attachmentList.Count > 0 && rand.NextDouble() <= m_messageData.attachProb)
                        {
                            int upperLimit = m_messageData.minAttachments + (int)(((double)m_messageData.maxAttachments - (double)m_messageData.minAttachments) * rand.NextDouble());
                            int attachmentIndex = 0;
                            while (attachmentIndex < upperLimit)
                            {
                                attachmentIndex++;
                                Attachment attachment = new Attachment(m_messageData.attachmentList[rand.Next() % m_messageData.attachmentList.Count], MediaTypeNames.Application.Octet);
                                message.Attachments.Add(attachment);
                            }
                            m_messageData.messagesWithAttachments++;
                        }

                        //
                        // Body...
                        message.Body = macroSupport.ParseBodyText(m_messageData, rand, m_messageData.body);
                        message.BodyEncoding = Encoding.UTF8;
                        message.IsBodyHtml = m_messageData.bodyIsHTML;

                        //
                        // Send the message..
                        try
                        {
                            smtpClient.Send(message);

                            //
                            // Keep our stats updated.
                            m_messageData.sentMessages++;
                            System.Console.Write(">");
                        }
                        catch (SmtpException)
                        {
                            System.Console.Write("X");
                        }
                    }
                }
            }
            catch (Exception exp)
            {
                System.Console.WriteLine("Thread " + this.m_messageData.threadId + " caught exception:" + exp);
            }
        }
    }
}
